﻿using System.Collections.Generic;
using UnityEditor;
using UnityEngine;

namespace HK.Editor.GUIEx.Protocol.Selection
{
    /// <summary>
    /// 委托定义 : 列表选中信息变更
    /// </summary>
    /// <param name="iIndex">索引</param>
    /// <param name="iSelected">选中标志位</param>
    public delegate void ListSelectionChanged(int iIndex, bool iSelected);
    
    /// <summary>
    /// 委托定义 : Element选中/未选中回调
    /// </summary>
    /// <param name="iIndex">Element索引</param>
    /// <param name="iProperty">Element Property</param>
    /// <param name="iSelected">选中/没选中</param>
    public delegate void ListElementSelected<in TType>(int iIndex, TType iProperty, bool iSelected);
    
    /// <summary>
    /// 接口 : 列表选中信息
    /// </summary>
    public interface IListSelection : IEnumerable<int> 
    {

        /// <summary>
        /// 第一个索引
        /// <para>-1 : 无效索引</para>
        /// </summary>
        int First { get; }
		
        /// <summary>
        /// 最后一个索引
        /// <para>-1 : 无效索引</para>
        /// </summary>
        int Last { get; }

        /// <summary>
        /// 长度
        /// </summary>
        int Length { get; }
        
        /// <summary>
        /// 运算符重载 : []
        /// </summary>
        /// <param name="iIndex">索引</param>
        int this[int iIndex] { get; set; }

        /// <summary>
        /// 校验是否包含指定索引
        /// </summary>
        /// <param name="iIndex">索引</param>
        /// <returns>true:包含; false:不包含;</returns>
        bool Contains(int iIndex);

        /// <summary>
        /// 移除索引
        /// </summary>
        /// <param name="iIndex">索引</param>
        void Remove(int iIndex);

        /// <summary>
        /// 清空
        /// </summary>
        /// <param name="iClearFirst"></param>
        /// <param name="iChangedCallBack">调用变更回调标志位</param>
        void Clear(bool iClearFirst = false, bool iChangedCallBack = true);

        /// <summary>
        /// 克隆
        /// </summary>
        /// <returns>列表选中信息</returns>
        IListSelection Clone();
        
        /// <summary>
        /// 还原值
        /// </summary>
        /// <param name="iData">数据</param>
        void RevertValues(object iData);

        /// <summary>
        /// 复制
        /// </summary>
        /// <param name="iList">List</param>
        void Duplicate(SerializedProperty iList);

        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="iList">List</param>
        void Delete(SerializedProperty iList);

        /// <summary>
        /// 转换成Array
        /// </summary>
        /// <returns>索引列表</returns>
        int[] ToArray();

#region Event

        /// <summary>
        /// 选中指定的索引
        /// </summary>
        /// <param name="iIndex">索引</param>
        /// <param name="iChangedCallBack">调用变更回调标志位</param>
        /// <returns>true:有变化; false:无变化;</returns>
        bool Select(int iIndex, bool iChangedCallBack = true);
        
        /// <summary>
        /// 排序
        /// </summary>
        void Sort();
        
        /// <summary>
        /// 排序
        /// </summary>
        /// <param name="iComparer">比较器</param>
        void Sort(System.Comparison<int> iComparer);

        /// <summary>
        /// 去除最小索引和最大索引之外的索引
        /// </summary>
        /// <param name="iMinIndex">最小索引</param>
        /// <param name="iMaxIndex">最大索引</param>
        void Trim(int iMinIndex, int iMaxIndex);

        /// <summary>
        /// 校验能否还原
        /// </summary>
        /// <param name="iList">List</param>
        /// <returns>true:可还原; false:不可还原;</returns>
        bool CanRevert(SerializedProperty iList);

#region Keyboard

        /// <summary>
        /// 没有任何动作是的选中操作
        /// <para>* Windows : Ctrl + Shift</para>
        /// <para>* macOs : Command + Shift</para>
        /// </summary>
        /// <param name="iIndex">索引</param>
        /// <param name="iEvent">Event</param>
        void SelectWhenNoAction(int iIndex, Event iEvent);

        /// <summary>
        /// Append 索引
        /// <para>* Windows : Ctrl + Shift</para>
        /// <para>* macOs : Command + Shift</para>
        /// </summary>
        /// <param name="iIndex">索引</param>
        /// <param name="iEvent">Event</param>
        void AppendWithAction(int iIndex, Event iEvent);

        #endregion

        #endregion

    }
}
